home *** CD-ROM | disk | FTP | other *** search
/ Risc World 3 / Risc World 3.iso / SOFTWARE / ISSUE6 / PD / PDF / DrawFile / c++ / GuiDrawFileRender < prev    next >
Text File  |  2003-02-14  |  12KB  |  390 lines

  1. //--------------------------------------------------------------------------
  2. //
  3. //   Copyright (c) 2002, Colin Granville
  4. //
  5. //   All rights reserved.
  6. //
  7. //   Redistribution and use in source and binary forms, with or
  8. //   without modification, are permitted provided that the following 
  9. //   conditions are met:
  10. //
  11. //      * Redistributions of source code must retain the above copyright 
  12. //        notice, this list of conditions and the following disclaimer.
  13. //
  14. //      * Redistributions in binary form must reproduce the above 
  15. //        copyright notice, this list of conditions and the following 
  16. //        disclaimer in the documentation and/or other materials 
  17. //        provided with the distribution.
  18. //
  19. //      * The name Colin Granville may not be used to endorse or promote 
  20. //        products derived from this software without specific prior 
  21. //        written permission.
  22. //
  23. //   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
  24. //   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
  25. //   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
  26. //   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
  27. //   COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
  28. //   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
  29. //   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
  30. //   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
  31. //   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
  32. //   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
  33. //   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
  34. //   OF THE POSSIBILITY OF SUCH DAMAGE.
  35. //
  36. //--------------------------------------------------------------------------
  37.  
  38. #include <iostream.h>
  39. #include "GuiDrawFileRender.h"
  40. #include "DrawFileParser.h"
  41. #include "DrawFileVisitor.h"
  42.  
  43. int mult(int a,int b)  {return int(double(a)*double(b)/(1<<16));}
  44.  
  45. void matrixMult(const DrawFileVisitor::Transform& a,
  46.             const DrawFileVisitor::Transform& b,
  47.             DrawFileVisitor::Transform& res)
  48. {
  49.   res.m0=mult(a.m0,b.m0)+mult(a.m1,b.m2); res.m1=mult(a.m0,b.m1)+mult(a.m1,b.m3);
  50.   res.m2=mult(a.m2,b.m0)+mult(a.m3,b.m2); res.m3=mult(a.m2,b.m1)+mult(a.m3,b.m3);
  51.   res.m4=res.m5=0;
  52. }
  53.  
  54. void transform(const DrawFileVisitor::Transform& m,int x,int y,int& xr,int& yr)
  55. {
  56.   xr=mult(x,m.m0)+mult(y,m.m2)+m.m4;
  57.   yr=mult(x,m.m1)+mult(y,m.m3)+m.m5;
  58. }
  59.  
  60. class DrawParser: public DrawFileParser
  61. {
  62.   public:
  63.     DrawParser(const GuiDrawFile& d) : draw(d) {}
  64.     virtual void* getObject(size_t start) const {return (void*)draw.getPtr(start);}
  65.     virtual size_t getSize() const              {return draw.getSize();}
  66.  private:
  67.     const GuiDrawFile& draw;
  68. };
  69.  
  70. //**************************************************************************
  71. //**************************************************************************
  72. //**************************************************************************
  73.  
  74. class Font
  75. {
  76.   public: 
  77.     Font(DrawFileParser& parser);
  78.     ~Font();
  79.     void setTable(size_t start) {table=start;}
  80.     void find(int number,size_t width,size_t height);
  81.  
  82.   private:
  83.     DrawFileParser& parser;
  84.     size_t          table;
  85.     int             number;
  86.     size_t          width;
  87.     size_t          height;
  88.     int             handle;
  89.     int             nameoffset;
  90. };
  91.  
  92. //**************************************************************************
  93.  
  94. Font::Font(DrawFileParser& p)
  95.   : parser(p),
  96.     table(0),
  97.     number(-1),
  98.     handle(0),
  99.     nameoffset(1)
  100. {
  101. }
  102.  
  103. //**************************************************************************
  104.  
  105. Font::~Font()
  106. {
  107.   if (handle) _swix(Font_LoseFont,_IN(0),handle);
  108. }
  109.  
  110. //**************************************************************************
  111.  
  112. void Font::find(int n,size_t w,size_t h)
  113. {
  114.   if (number==n && width==w && height==h) return;
  115.  
  116.   unsigned char* start=(unsigned char*)parser.getObject(table);
  117.   unsigned char* p;
  118.  
  119.   unsigned char num;
  120.   if (number==n)
  121.   {
  122.     p=start+nameoffset;
  123.     num=number;
  124.   }
  125.   else
  126.   {
  127.     p=start;
  128.     while (num=*p++,!(num==n || num==0))
  129.     {
  130.       while (*p!=0) p++;
  131.       p++;
  132.     }
  133.     nameoffset=p-start;
  134.   }
  135.   int oldHandle=handle;
  136.   int newHandle=0;
  137.   if (num==0 || _swix(Font_FindFont,_INR(1,5)|_OUT(0),(char*)p,w/40,h/40,0,0,&newHandle))
  138.   {
  139.     _swix(Font_FindFont,_INR(1,5)|_OUT(0),"Trinity.Medium",w/40,h/40,0,0,&newHandle);
  140.   }
  141.  
  142.   if (newHandle)
  143.   {
  144.     if (oldHandle) _swix(Font_LoseFont,_IN(0),oldHandle);
  145.     handle=newHandle;
  146.     number=n;
  147.     width =w;
  148.     height=h;
  149.   }
  150. }
  151.  
  152. //**************************************************************************
  153. //**************************************************************************
  154. //**************************************************************************
  155.  
  156.  
  157. //**************************************************************************
  158.  
  159. class Renderer : public DrawFileVisitor
  160. {
  161.   public: 
  162.     Renderer(DrawFileParser& parser,
  163.              const DrawFileVisitor::Transform& t,
  164.              const GuiBBox& clipBox,
  165.              bool toPrinter);
  166.     ~Renderer();
  167.  
  168.   private:
  169.     DrawFileParser&  parser;
  170.     const Transform& matrix;
  171.     GuiBBox          clipBox;
  172.     Font             font;
  173.     unsigned int     blendFont;
  174.  
  175.     virtual int fontTable(size_t start);
  176.     virtual int transformedTextObject(size_t start);
  177.     virtual int transformedSpriteObject(size_t start);
  178.     virtual int pathObject(size_t start);
  179.  
  180. };
  181.  
  182. //**************************************************************************
  183. class Convert
  184. {
  185.   public:
  186.     Convert(double* matrix) : ctm(matrix) {}
  187.  
  188.     void convert(double x1, double y1, int& x2, int& y2)
  189.     {
  190.       x2 = (int)(ctm[0] * x1 + ctm[2] * y1);
  191.       y2 = (int)(ctm[1] * x1 + ctm[3] * y1);
  192.     }
  193.   private:
  194.     double* ctm;
  195. };
  196.  
  197. inline void set(GuiBBox& b,int x,int y)
  198. {
  199.   if (x<b.xmin) b.xmin=x;
  200.   if (x>b.xmax) b.xmax=x;
  201.   if (y<b.ymin) b.ymin=y;
  202.   if (y>b.ymax) b.ymax=y;
  203. }
  204.  
  205. Renderer::Renderer(DrawFileParser& p,
  206.                    const DrawFileVisitor::Transform& t,
  207.                    const GuiBBox& c,
  208.                    bool blend)
  209.   : parser(p),
  210.     matrix(t),
  211.     font(p),
  212.     blendFont(blend?(1<<11):0)
  213. {
  214.    
  215.     //transform bounding box using inverse matrix;
  216.     double m[4], im[4];
  217.     m[0]=((double)t.m0)/0x10000;
  218.     m[1]=((double)t.m1)/0x10000;
  219.     m[2]=((double)t.m2)/0x10000;
  220.     m[3]=((double)t.m3)/0x10000;
  221.     double det=1/(m[0]*m[3] - m[1]*m[2]);
  222.     im[0]=m[3]*det;
  223.     im[1]=-m[1]*det;
  224.     im[2]=-m[2]*det;
  225.     im[3]=m[0]*det;
  226.  
  227.     Convert cvt(im);
  228.     int x,y;
  229.     cvt.convert(double(c.xmin*256-t.m4) ,double(c.ymin*256-t.m5),x,y);
  230.     clipBox.xmin=clipBox.xmax=x;
  231.     clipBox.ymin=clipBox.ymax=y;
  232.  
  233.     cvt.convert(double(c.xmin*256-t.m4),double(c.ymax*256-t.m5),x,y);
  234.     set(clipBox,x,y);    
  235.     cvt.convert(double(c.xmax*256-t.m4),double(c.ymax*256-t.m5),x,y);
  236.     set(clipBox,x,y);
  237.     cvt.convert(double(c.xmax*256-t.m4),double(c.ymin*256-t.m5),x,y);
  238.     set(clipBox,x,y);
  239. };
  240.  
  241. //**************************************************************************
  242.  
  243. Renderer::~Renderer() {}
  244.  
  245. //**************************************************************************
  246.  
  247. int Renderer::fontTable(size_t start) 
  248. {
  249.   font.setTable(start+sizeof(DrawFileVisitor::FontTable));
  250.  
  251.   return 1;
  252. }
  253.  
  254. //**************************************************************************
  255.  
  256. int Renderer::transformedTextObject(size_t start)
  257. {
  258.   DrawFileVisitor::TransformedTextObject& text=
  259.           *(DrawFileVisitor::TransformedTextObject*)parser.getObject(start);
  260.   if (!clipBox.overlap(text.bounds)) return 1;
  261.  
  262.   font.find(text.font,text.fontXSize,text.fontYSize);
  263.   _swix(ColourTrans_SetFontColours,_INR(0,3),0,text.backColour,text.foreColour,14);
  264.  
  265.   DrawFileVisitor::Transform res;
  266.   matrixMult(matrix,text.matrix,res);
  267.   int x,y;
  268.   transform(matrix,text.x,text.y,x,y);
  269.  
  270.   _swix(Font_Paint,_INR(0,7),0,text.getText(),(1<<6)|(1<<8)|blendFont,x*25/16,y*25/16,0,&res,0);
  271.   return 1;
  272. }
  273.  
  274. //**************************************************************************
  275.  
  276. int Renderer::transformedSpriteObject(size_t start)
  277. {
  278.   DrawFileVisitor::TransformedSpriteObject* sprite=
  279.           (DrawFileVisitor::TransformedSpriteObject*)parser.getObject(start);
  280.   if (!clipBox.overlap(sprite->bounds)) return 1;
  281.   DrawFileVisitor::Transform res;
  282.   matrixMult(matrix,sprite->matrix,res);
  283.   transform(matrix,sprite->matrix.m4,sprite->matrix.m5,res.m4,res.m5);
  284.  
  285.   int i;
  286.   int tableSize=0;
  287.   char* table=0;
  288.   for (i=0;i<2;i++)
  289.   {
  290.     sprite=(DrawFileVisitor::TransformedSpriteObject*)parser.getObject(start);
  291.     _swix(ColourTrans_SelectTable,_INR(0,5)|_OUT(4),
  292.           sprite->getSprite(),sprite->getSprite(),-1,-1,table,3|(1<<4),&tableSize);
  293.     if (i==1 || tableSize==0) break;
  294.     
  295.     table=new char[tableSize];
  296.     if (!table) break;
  297.   }
  298.  
  299.   _swix(OS_SpriteOp,_INR(0,7),0x200+56,
  300.                       sprite->getSprite(),sprite->getSprite(),0,0,8 | (1<<5),&res,table);
  301.   delete [] table;
  302.   return 1;
  303. }
  304.  
  305. //**************************************************************************
  306.  
  307. int Renderer::pathObject(size_t start)
  308. {
  309.   DrawFileVisitor::PathObject& path=*(DrawFileVisitor::PathObject*)parser.getObject(start);
  310.   if (!clipBox.overlap(path.bounds)) return 1;
  311.   if (path.fillColour != -1)
  312.   {
  313.     _swix(ColourTrans_SetGCOL,_IN(0)|_INR(3,4),path.fillColour,0x100,0);
  314. //    size_t s=sizeof(DrawFileVisitor::PathObject);
  315. //    _swix(Draw_Fill,_INR(0,3),path.pathStart(),((path.pathStyle & (1<<6))?0x32:0x30),&matrix,0);
  316.     _swix(Draw_Fill,_INR(0,3),path.pathStart(),
  317.                        ((path.pathStyle & (1<<6))?0x32:0)/*0x3a:0x38)*/,&matrix,0);
  318.  
  319.     if (path.outlineColour == -1 && blendFont)
  320.     {
  321.       // bodge to display areas which disappear on screen
  322.       // only do this for screen rendering
  323.       // blendFont <> 0 if drawing to screen
  324.       struct
  325.       {
  326.         unsigned int style;
  327.         int      mitreJoin;
  328.         unsigned int leadCap;
  329.         unsigned int trailCap;
  330.       } capAndJoin;
  331.       capAndJoin.style=0x00010101;
  332.       capAndJoin.mitreJoin=0;
  333.       capAndJoin.leadCap=0;
  334.       capAndJoin.trailCap=capAndJoin.leadCap;
  335.       _swix(Draw_Stroke,_INR(0,6),path.pathStart(),0,&matrix,0,0,&capAndJoin,0);
  336.    }
  337.   }
  338.  
  339.   if (path.outlineColour != -1)
  340.   {
  341.     _swix(ColourTrans_SetGCOL,_IN(0)|_INR(3,4),path.outlineColour,0x100,0);
  342.     struct
  343.     {
  344.       unsigned int style;
  345.       int      mitreJoin;
  346.       unsigned int leadCap;
  347.       unsigned int trailCap;
  348.     } capAndJoin;
  349.     
  350.     capAndJoin.style= ( (path.pathStyle & 3) |
  351.                         (((path.pathStyle>>4) & 3)<<8) |
  352.                         (((path.pathStyle>>2) & 3)<<16) );
  353.     capAndJoin.leadCap=( (path.capWidth*16) | ((path.capHeight*16)<<16) );
  354.     capAndJoin.trailCap=capAndJoin.leadCap;
  355.    // capAndJoin.mitreJoin=((path.outlineWidth*4)<<8);
  356.     capAndJoin.mitreJoin=8<<16;
  357.    _swix(Draw_Stroke,_INR(0,6),path.pathStart(),0x38,&matrix,0,
  358.                                 path.outlineWidth,&capAndJoin,
  359.                                 path.dashStart());
  360.   }
  361.  
  362.  
  363.   return 1;
  364. }
  365.  
  366. //**************************************************************************
  367. //**************************************************************************
  368. //**************************************************************************
  369.  
  370.  
  371. _kernel_oserror* GuiDrawFile_render(const GuiDrawFile& draw,
  372.                                     const DrawFileVisitor::Transform* mat,
  373.                                     const GuiBBox* clipBox,
  374.                                     bool  blendFonts)
  375. {
  376.   static GuiBBox                    defClipBox={0,0,0x7fff,0x7fff};
  377.   static DrawFileVisitor::Transform defMatrix={(1<<16),0,0,(1<<16),0,0};
  378.  
  379.   DrawParser drawfile(draw);
  380.   Renderer renderer(drawfile,
  381.                     *(mat?mat:&defMatrix),
  382.                     *(clipBox?clipBox:&defClipBox),
  383.                     blendFonts);
  384.   drawfile.accept(renderer);
  385.   //DrawFile_Render
  386.   //return _swix(0x45540,_INR(0,5),0,draw.getPtr(0),size,
  387.   //                (mat?mat:&defMatrix),(clipBox?clipBox:&defClipBox),0);
  388.   return 0;
  389. };
  390.